/** 记录前端日志到文件 */
let count = 1
const fileName = '话务日志（请勿删除，请忽略该文件）'
// 触发保存最大大小
const maxSize = 2500 * 2
// 过滤条件
const filtersList = [(method, url) => {
  return /callService/.test(url) && !/\/queryQueueInfo/.test(url)
}, (method, url) => {
  return /callLog/.test(url) && !/page$/.test(url)
}, /\/crm\/record/, /\/crm\/opty\/newPage/]
// 排除的头部信息
const exclude = ['Content-Type', 'Accept']
let logResultList = []

let stertTime = new Date()
// 过滤器
function filter(method, url) {
  return filtersList.some(e => {
    if (e instanceof RegExp && e.test(url)) {
      return true
    } else if (typeof e === 'string' && e === url) {
      return true
    } else if (e instanceof Function) {
      return e(method, url)
    }
    return false
  })
}
// 检查是否生成日志文件
function genLogFile() {
  if (logResultList.length > maxSize) {
    saveLog()
  }
}
function saveLog() {
  if (logResultList.length <= 0) {
    return
  }
  const logData = logDataToString(logResultList)
  const env = ObjectTOString(getEnvInfo())
  let performance = ''
  try {
    performance = ObjectTOString(getPerformance())
  } catch (error) {
    console.log(error)
  }
  const str = `浏览器信息  \r\n ${env} \r\n 浏览器性能数据 \r\n ${performance} \r\n 请求数据 \r\n ${logData}`
  var textFileAsBlob = new Blob([str], { type: 'text/plain' })
  var downloadLink = document.createElement('a')
  downloadLink.download = `${fileName}(${stertTime.toLocaleString()}--${new Date().toLocaleString()})-${count}.log`
  count++
  downloadLink.href = window.URL.createObjectURL(textFileAsBlob)
  downloadLink.click()
  stertTime = new Date()
  logResultList = []
}
// 设定触发保存时机
window.addEventListener('unload', () => {
  saveLog()
})
window.addEventListener('keydown', e => {
  if (e.ctrlKey && e.code === 'ArrowUp') {
    saveLog()
  }
})

// 抽取要保存的信息
function getResult(message, e, reqHeader, method, url, body) {
  const target = e.target
  if (target.readyState !== 4) {
    return
  }
  const { readyState, responseText, responseType, responseURL, status, statusText, timeout } = target
  // const resHeader = target.getAllResponseHeaders()
  const resHeader = ''
  const time = new Date().toLocaleString()
  let bodyContent
  if (body instanceof FormData) {
    bodyContent = {}
    for (const [k, v] of body.entries()) {
      if (v instanceof File) {
        continue
      }
      bodyContent[k] = v
    }
  } else {
    bodyContent = body
  }
  logResultList.push({
    message, method, url, reqHeader, bodyContent, readyState, resHeader, responseText, responseType, responseURL, status, statusText, timeout, time
  })
  genLogFile()
}
function readystatechange(...params) {
  getResult('readystatechange', ...params)
}
function errorFun(...params) {
  getResult('readystatechange', ...params)
}
const eventList = {
  readystatechange: readystatechange,
  error: errorFun
}

// 覆写XMLHttpRequest
// 收集请求方式url
const xhrOpen = window.XMLHttpRequest.prototype.open
window.XMLHttpRequest.prototype.open = function(...param) {
  this._method = param[0]
  this._url = param[1]
  return xhrOpen.call(this, ...param)
}
// 绑定事件，收集请求体
const xhrSend = window.XMLHttpRequest.prototype.send
window.XMLHttpRequest.prototype.send = function(body) {
  if (filter(this._method, this._url)) {
    for (const [key, value] of Object.entries(eventList)) {
      this.addEventListener(key, e => {
        value(e, this._header, this._method, this._url, body)
      })
    }
  }
  return xhrSend.call(this, body)
}

// 收集请求头
const xhrSetRequestHeader = window.XMLHttpRequest.prototype.setRequestHeader
window.XMLHttpRequest.prototype.setRequestHeader = function(name, value) {
  if (!this._header) {
    this._header = {}
  }
  if (!exclude.includes(name)) {
    this._header[name] = value
  }
  return xhrSetRequestHeader.call(this, name, value)
}

// 获取浏览器环境信息
function getEnvInfo() {
  if (!window.navigator) {
    return ''
  }
  const env = window.navigator
  const connection = env.connection || {}
  return {
    frontEndVersion: '2',
    appCodeName: env.appCodeName,
    appName: env.appName,
    appVersion: env.appVersion,
    deviceMemory: env.deviceMemory,
    language: env.language,
    onLine: env.onLine,
    platform: env.platform,
    product: env.product,
    productSub: env.productSub,
    userAgent: env.userAgent,
    vendor: env.vendor,
    vendorSub: env.vendorSub,
    downlink: connection.downlink,
    effectiveType: connection.effectiveType,
    rtt: connection.rtt,
    saveData: connection.saveData
  }
}
// ObjectTOString
const ts = Object.prototype.toString
function ObjectTOString(obj) {
  const t = []
  if (typeof obj === 'string') {
    t.push(obj)
  } else if (ts.call(obj) === '[object Object]' || ts.call(obj) === '[object Array]') {
    for (const [k, v] of Object.entries(obj)) {
      if (ts.call(v) === '[object Object]' || ts.call(v) === '[object Array]') {
        t.push(`${k}:${ObjectTOString(v)}`)
      } else {
        t.push(`${k}:${v}`)
      }
    }
  }
  return t.join(',')
}

function logDataToString(logData) {
  let t = ''
  for (const [k, v] of Object.entries(logData)) {
    t += `${k}:${ObjectTOString(v)} \r\n`
  }
  return t
}

// 获取浏览器性能数据
function getPerformance() {
  const data = {
    timeOrigin: performance.timeOrigin
  }
  try {
    data.memory = {
      jsHeapSizeLimit: performance.memory.jsHeapSizeLimit,
      totalJSHeapSize: performance.memory.totalJSHeapSize,
      usedJSHeapSize: performance.memory.usedJSHeapSize
    }
  } catch (error) {
    console.log(error)
  }
  try {
    data.timing = {
      connectEnd: performance.timing.connectEnd,
      connectStart: performance.timing.connectStart,
      domComplete: performance.timing.domComplete,
      domContentLoadedEventEnd: performance.timing.domContentLoadedEventEnd,
      domContentLoadedEventStart: performance.timing.domContentLoadedEventStart,
      domInteractive: performance.timing.domInteractive,
      domLoading: performance.timing.domLoading,
      domainLookupEnd: performance.timing.domainLookupEnd,
      domainLookupStart: performance.timing.domainLookupStart,
      fetchStart: performance.timing.fetchStart,
      loadEventEnd: performance.timing.loadEventEnd,
      loadEventStart: performance.timing.loadEventStart,
      navigationStart: performance.timing.navigationStart,
      redirectEnd: performance.timing.redirectEnd,
      redirectStart: performance.timing.redirectStart,
      requestStart: performance.timing.requestStart,
      responseEnd: performance.timing.responseEnd,
      responseStart: performance.timing.responseStart,
      secureConnectionStart: performance.timing.secureConnectionStart,
      unloadEventEnd: performance.timing.unloadEventEnd,
      unloadEventStart: performance.timing.unloadEventStart
    }
  } catch (error) {
    console.log(error)
  }
  try {
    data.eventCountsSize = performance.eventCounts.size
  } catch (error) {
    console.log(error)
  }
  try {
    data.navigation = {
      redirectCount: performance.navigation.redirectCount,
      type: performance.navigation.type
    }
  } catch (error) {
    console.log(error)
  }
  return data
}

// 网络发生变化
window.navigator.connection.onchange = (e) => {
  console.log(e)
  const t = e.target
  logResultList.push(`网络：[downlink:${t.downlink}-effectiveType:${t.effectiveType}-rtt:${t.rtt}]`)
}

